package com.iflytek.jcy.supervise.job.component.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.stream.Collectors;

import com.iflytek.jcy.supervise.job.common.pojo.CommonResponse;
import com.iflytek.jcy.supervise.job.common.enums.ResultEnum;
import com.iflytek.jcy.supervise.job.common.exception.BaseException;
import com.iflytek.jcy.supervise.job.common.exception.InvalidParameterException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Controller层统一异常处理类
 *
 * @author <a href=mailto:ktyi@iflytek.com>伊开堂</a>
 * @date 2019/3/4 14:46
 */
@ControllerAdvice
public class ExpcetionHandler {
    private static final Logger logger = LoggerFactory.getLogger(ExpcetionHandler.class);

    /**
     * 处理自定义的业务异常
     */
    @ExceptionHandler(BaseException.class)
    @ResponseBody
    public CommonResponse handleBusinessException(Throwable e, HttpServletRequest request,
            HttpServletResponse response) {
        BaseException ee = (BaseException) e;
        logger.warn("业务异常", ee);
        return new CommonResponse(ee.getResultType());
    }

    /**
     * 处理Web层参数校验失败异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public CommonResponse handleMethodArgumentNotValidException(Throwable e, HttpServletRequest request,
            HttpServletResponse response) {
        MethodArgumentNotValidException ee = (MethodArgumentNotValidException) e;
        logger.warn("参数验证未通过", ee);

        BindingResult bindingResult = ee.getBindingResult();
        if (bindingResult == null) {
            return new CommonResponse(ResultEnum.INVALID_PARAMETER);
        }

        List<FieldError> errorList = bindingResult.getFieldErrors();
        if (CollectionUtils.isEmpty(errorList)) {
            return new CommonResponse(ResultEnum.INVALID_PARAMETER);
        }

        String errorMessages = errorList.stream().map(error -> {
            String defaultMessage = error.getDefaultMessage();
            String field = error.getField();
            return defaultMessage.contains(field) ? defaultMessage : field + defaultMessage;
        }).filter(StringUtils::isNotBlank).collect(Collectors.joining("; "));
        return CommonResponse.failed(ResultEnum.INVALID_PARAMETER, errorMessages);
    }

    /**
     * 处理自定义参数校验异常
     */
    @ExceptionHandler(InvalidParameterException.class)
    @ResponseBody
    public CommonResponse handleInvalidParameterException(Throwable e, HttpServletRequest request,
            HttpServletResponse response) {
        InvalidParameterException ee = (InvalidParameterException) e;
        logger.warn("自定义参数验证未通过", ee);
        return new CommonResponse(ee.getResultType());

    }

    /**
     * 处理接口参数缺少异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public CommonResponse handleMissingServletRequestParameterException(Throwable e, HttpServletRequest request,
            HttpServletResponse response) {
        logger.warn("参数缺失", e);
        return CommonResponse.failed(ResultEnum.PARAMETER_MISSING, e.getMessage());
    }

    /**
     * 处理http方法错误异常
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public CommonResponse handleHttpRequestMethodNotSupportedException(Throwable e, HttpServletRequest request,
            HttpServletResponse response) {
        HttpRequestMethodNotSupportedException ee = (HttpRequestMethodNotSupportedException) e;
        String requestMethod = ee.getMethod();
        logger.warn("该接口不支持此http方法: {}, 支持的方法有: {}", requestMethod, StringUtils.join(ee.getSupportedMethods(), ", "));
        return CommonResponse.failed(ResultEnum.HTTP_METHOD_NOT_SUPPORT,
                ResultEnum.HTTP_METHOD_NOT_SUPPORT.getDesc() + ": " + requestMethod);
    }


    @ExceptionHandler(Throwable.class)
    @ResponseBody
    public CommonResponse handleAllException(HttpServletRequest req, HttpServletResponse rep, Throwable e) {
        StringBuffer requestURL = req.getRequestURL();
        String queryString = req.getQueryString();
        if (StringUtils.isNotBlank(queryString)) {
            requestURL.append("?").append(queryString);
        }

        logger.warn("Controller层抛出未知异常, url: {}", requestURL, e);
        return CommonResponse.failed(ResultEnum.FAILED);
    }
}